
package com.studiofortress.sf.util.structure;

import com.studiofortress.sf.structure.MainLoop;
import com.studiofortress.sf.structure.MainLoopEvent;

/**
 * This is a mainloop event that updates a delta time value. Delta time is the
 * multiplyer that will take you from the current frame rate to your ideal frame
 * rate.
 *
 * For example if the last frame was running at half the ideal frame rate, then
 * the delta time is 2 (it's twice as much). If the last frame was running at
 * three times the ideal frame rate, then the delta time is 0.333 (one third).
 * 
 * By multiplying movement and other update values by the delta time it allows
 * the game to run at the same speed independantly of the frame rate.
 *
 * @author Joseph Lenton - JosephLenton@StudioFortress.com
 */
public class DeltaTimeEvent implements MainLoopEvent
{
    private static final int NO_TIME = 0;
    private static final int DEFAULT_PERFECT_FRAME_RATE = 60;

    private final double perfectFrameTime;
    private float deltaTime;
    private double lastTime;

    /**
     * Creates a new DeltaTimeEvent with it's own pre-set perfect frame rate.
     * This is 60 frames per second.
     */
    public DeltaTimeEvent()
    {
        this( DEFAULT_PERFECT_FRAME_RATE );
    }

    /**
     * This will use the given frameRate as an indicator on how fast the game
     * should be running at. The delta time value is then the multiplyer to get
     * from the real framerate to the given framerate.
     * @param frameRate The framerate this application should ideally be running at.
     */
    public DeltaTimeEvent(final int frameRate)
    {
        if (frameRate <= 0) {
            throw new IllegalArgumentException("The given frame rate cannot be less then or equal to 0.");
        }

        perfectFrameTime = 1000.0 / (double)frameRate;
        deltaTime = 1.0f;
        lastTime = NO_TIME;
    }

    /**
     * Updates the delta time value to it's new value.
     * @param mainLoop Ignored.
     */
    public void action(MainLoop mainLoop)
    {
        final double now = System.currentTimeMillis();
        if ( lastTime != NO_TIME ) {
            deltaTime = (float) ((now - lastTime) / perfectFrameTime);
        }
        lastTime = now;
    }

    /**
     * @return The current delta time.
     */
    public float getDeltaTime()
    {
        return deltaTime;
    }
}
